﻿using AspNetCoreRateLimit;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using System;
using System.Threading.Tasks;

namespace YNTK.API.Core
{
    /// <summary>
    /// ElmahIoRateLimitConfiguration是一个IRateLimitConfiguration接口的实现，
    /// 它将告诉AspNetCoreRateLimit如何对请求进行分组
    /// 重要的部分在于ResolveClient方法
    /// 在这里，我们提取api_key参数并将其作为字符串返回AspNetCoreRateLimit以用作组键
    /// 现在，当使用相同参数发出超过每分钟500个请求或每小时3600个请求时AspNetCoreRateLimit返回状态代码
    /// </summary>
    public class ElmahIoRateLimitConfiguration : RateLimitConfiguration
    {
        private IHttpContextAccessor _httpContextAccessor;

        public ElmahIoRateLimitConfiguration(
            IHttpContextAccessor httpContextAccessor,
            IOptions<IpRateLimitOptions> ipOptions,
            IOptions<ClientRateLimitOptions> clientOptions)
                : base(ipOptions, clientOptions)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        public override void RegisterResolvers()
        {
            ClientResolvers.Add(new ClientQueryStringResolveContributor(_httpContextAccessor));
        }
    }

    public class ClientQueryStringResolveContributor : IClientResolveContributor
    {
        private IHttpContextAccessor httpContextAccessor;

        public ClientQueryStringResolveContributor(IHttpContextAccessor httpContextAccessor)
        {
            this.httpContextAccessor = httpContextAccessor;
        }

        public async Task<string> ResolveClientAsync(HttpContext httpContex)
        {          
            return await Task.Run(() => {
                string api_key = "";
                var request = httpContextAccessor.HttpContext?.Request;
                var queryDictionary =
                    Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(
                        request.QueryString.ToString());
                if (queryDictionary.ContainsKey("api_key")
                    && !string.IsNullOrWhiteSpace(queryDictionary["api_key"]))
                {
                    api_key= queryDictionary["api_key"];
                }
                api_key= Guid.NewGuid().ToString();
                return api_key;
            }).ConfigureAwait(false);
        }

    }
}
